global with sharing class DataSourceUtil{
    static Boolean testFlag = false;

    Webservice static String deleteUsers(String str){
//        for(CallidusDataSource__c[] cds : [select id from CallidusDataSource__c])
  //          delete cds;
        return 'success';
    }
    
    Webservice static CallidusDataSource__c getPlanParticipantDetails(Id dsId)
    {
        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject cdsObj = new CallidusDataSource__c();

        Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(cdsObj);
        
        String[] cdsExpectedFields = new String[]{'Id','Name','FirstName__c','LastName__c','UserID__c','UserRoleId__c','UserRoleName__c','Name1__c','Name2__c','Name3__c','Name4__c','Name5__c','Name6__c','Name7__c','Name8__c','Name9__c','Name10__c','Name11__c','Name12__c','Name13__c','Name14__c','Name15__c','Name16__c','Name17__c','Name18__c','Name19__c','Name20__c','Name21__c','Name22__c','Name23__c','Name24__c','Name25__c','Name26__c','Name27__c','Name28__c','Name29__c','Name30__c','Value1__c','Value2__c','Value3__c','Value4__c','Value5__c','Value6__c','Value7__c','Value8__c','Value9__c','Value10__c','Value11__c','Value12__c','Value13__c','Value14__c','Value15__c','Value16__c','Value17__c','Value18__c','Value19__c','Value20__c','Value21__c','Value22__c','Value23__c','Value24__c','Value25__c','Value26__c','Value27__c','Value28__c','Value29__c','Value30__c','Name31__c','Name32__c','Name33__c','Name34__c','Name35__c','Name36__c','Name37__c','Name38__c','Name39__c','Name40__c','Name41__c','Name42__c','Name43__c','Name44__c','Name45__c','Name46__c','Name47__c','Name48__c','Name49__c','Name50__c','Name51__c','Name52__c','Name53__c','Name54__c','Value31__c','Value32__c','Value33__c','Value34__c','Value35__c','Value36__c','Value37__c','Value38__c','Value39__c','Value40__c','Value41__c','Value42__c','Value43__c','Value44__c','Value45__c','Value46__c','Value47__c','Value48__c','Value49__c','Value50__c','Value51__c','Value52__c','Value53__c','Value54__c'}; 
        Set<String> allowedFields = dacu.getAccessibleFields(cdsObj, fieldMap, cdsExpectedFields);
        
        String constructSoql = '';
        CallidusDataSource__c ds = null;
        if(!allowedFields.isEmpty())
        {
            constructSoql = 'Select ';
            for(String roField: allowedFields)
            {
                constructSoql += roField+', ';
            }
            constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
            constructSoql += ' from CallidusDataSource__c where id = :dsId';
            
            if(constructSoql.contains('Id'))
            {
                ds = Database.query(constructSoql);
            }
        }
        return ds;
        //return null;
    }
    
    /**
     *  This method code runs in Batch mode.
     */
    Webservice static String purgeUsers(String str)
    {
        SObject sObj = new CallidusDataSource__c();
        DataAccessControlUtil dacu = new DataAccessControlUtil();   
        String message = dacu.isUpdateableObjectByUser(sObj);
        
        //Satisfies for Users with Update permission on CallidusDataSorce__c object
        if(message.equalsIgnoreCase('success'))
        {
            //get all fields of the object
            Map<String, Schema.Sobjectfield> fieldMap = dacu.getFieldMap(sObj);
            
            //Note: Whenever a new Custom field has to be updated, add it to the below Set.
            //Reason: The size of the below set will be compared with the size of the filtered set 
            Set<String> fieldsToBeUpdatedList = new Set<String>{'Name1__c','Name2__c','Name3__c','Name4__c','Name5__c','Name6__c','Name7__c','Name8__c','Name9__c','Name10__c','Name11__c','Name12__c','Name13__c','Name14__c','Name15__c','Name16__c','Name17__c','Name18__c','Name19__c','Name20__c','Name21__c','Name22__c','Name23__c','Name24__c','Name25__c','Name26__c','Name27__c','Name28__c','Name29__c','Name30__c','Value1__c','Value2__c','Value3__c','Value4__c','Value5__c','Value6__c','Value7__c','Value8__c','Value9__c','Value10__c','Value11__c','Value12__c','Value13__c','Value14__c','Value15__c','Value16__c','Value17__c','Value18__c','Value19__c','Value20__c','Value21__c','Value22__c','Value23__c','Value24__c','Value25__c','Value26__c','Value27__c','Value28__c','Value29__c','Value30__c','Name31__c','Name32__c','Name33__c','Name34__c','Name35__c','Name36__c','Name37__c','Name38__c','Name39__c','Name40__c','Name41__c','Name42__c','Name43__c','Name44__c','Name45__c','Name46__c','Name47__c','Name48__c','Name49__c','Name50__c','Name51__c','Name52__c','Name53__c','Name54__c','Value31__c','Value32__c','Value33__c','Value34__c','Value35__c','Value36__c','Value37__c','Value38__c','Value39__c','Value40__c','Value41__c','Value42__c','Value43__c','Value44__c','Value45__c','Value46__c','Value47__c','Value48__c','Value49__c','Value50__c','Value51__c','Value52__c','Value53__c','Value54__c'};
            
            //Filter the above list to get the fields that can be updated by the User. 
            Set<String> filteredList = dacu.getFilteredUpdateableFields(fieldMap, fieldsToBeUpdatedList);

            List<CallidusDataSource__c> dataSourceList = new List<CallidusDataSource__c>();
    
            String constructSoql = '';
            
            //Enters only if the filteredList size is equivalent to the size of expected updateable fields List 
            if(filteredList.size() == fieldsToBeUpdatedList.size())
            {
                constructSoql = 'Select ';
                for(String field: filteredList)
                {
                    constructSoql += field+', ';
                }
                constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
                //Not filtering based on the OwnerId. The DataSource is common to all the Admins of the org. 
                constructSoql += ' from CallidusDataSource__c ';
                
                if(constructSoql.contains('Name1__c'))
                {
                    if(str == 'test')
                        dataSourceList = Database.query(constructSoql+' limit 1');//[Select Id,Name1__c, Name2__c, Name3__c, Name4__c, Name5__c, Name6__c, Name7__c, Name8__c, Name9__c, Name10__c, Name11__c, Name12__c, Name13__c, Name14__c, Name15__c, Name16__c, Name17__c, Name18__c, Name19__c, Name20__c, Name21__c, Name22__c, Name23__c, Name24__c, Name25__c, Name26__c, Name27__c, Name28__c, Name29__c, Name30__c, Value1__c, Value2__c, Value3__c, Value4__c, Value5__c, Value6__c, Value7__c, Value8__c, Value9__c, Value10__c, Value11__c, Value12__c, Value13__c, Value14__c, Value15__c, Value16__c, Value17__c, Value18__c, Value19__c, Value20__c, Value21__c, Value22__c, Value23__c, Value24__c, Value25__c, Value26__c, Value27__c, Value28__c, Value29__c, Value30__c, Name31__c, Name32__c, Name33__c, Name34__c, Name35__c, Name36__c, Name37__c, Name38__c, Name39__c, Name40__c, Name41__c, Name42__c, Name43__c, Name44__c, Name45__c, Name46__c, Name47__c, Name48__c, Name49__c, Name50__c, Name51__c, Name52__c, Name53__c, Name54__c, Value31__c, Value32__c, Value33__c, Value34__c, Value35__c, Value36__c, Value37__c, Value38__c, Value39__c, Value40__c, Value41__c, Value42__c, Value43__c, Value44__c, Value45__c, Value46__c, Value47__c, Value48__c, Value49__c, Value50__c, Value51__c, Value52__c, Value53__c, Value54__c from CallidusDataSource__c limit 1];
                    else
                    {
                        for(CallidusDataSource__c[] callidusUsers : Database.query(constructSoql))//[Select Id,Name1__c, Name2__c, Name3__c, Name4__c, Name5__c, Name6__c, Name7__c, Name8__c, Name9__c, Name10__c, Name11__c, Name12__c, Name13__c, Name14__c, Name15__c, Name16__c, Name17__c, Name18__c, Name19__c, Name20__c, Name21__c, Name22__c, Name23__c, Name24__c, Name25__c, Name26__c, Name27__c, Name28__c, Name29__c, Name30__c, Value1__c, Value2__c, Value3__c, Value4__c, Value5__c, Value6__c, Value7__c, Value8__c, Value9__c, Value10__c, Value11__c, Value12__c, Value13__c, Value14__c, Value15__c, Value16__c, Value17__c, Value18__c, Value19__c, Value20__c, Value21__c, Value22__c, Value23__c, Value24__c, Value25__c, Value26__c, Value27__c, Value28__c, Value29__c, Value30__c, Name31__c, Name32__c, Name33__c, Name34__c, Name35__c, Name36__c, Name37__c, Name38__c, Name39__c, Name40__c, Name41__c, Name42__c, Name43__c, Name44__c, Name45__c, Name46__c, Name47__c, Name48__c, Name49__c, Name50__c, Name51__c, Name52__c, Name53__c, Name54__c, Value31__c, Value32__c, Value33__c, Value34__c, Value35__c, Value36__c, Value37__c, Value38__c, Value39__c, Value40__c, Value41__c, Value42__c, Value43__c, Value44__c, Value45__c, Value46__c, Value47__c, Value48__c, Value49__c, Value50__c, Value51__c, Value52__c, Value53__c, Value54__c from CallidusDataSource__c])
                        {        
                            for(CallidusDataSource__c user:callidusUsers)
                            {
                                /**
                                 *  If each field is individually assigned a value, there is a possible chance that limitation of 2,00,000 script statements can be exceeded or may hit the heap size limitation.
                                 *  We faced this for one of our Customers.
                                 *  Because of the above reason, not following sObject.put(f, null) approach for the fields that are not updateable.
                                 */
                                user.Name1__c = user.Name2__c = user.Name3__c = user.Name4__c = user.Name5__c = user.Name6__c = user.Name7__c = user.Name8__c = user.Name9__c = user.Name10__c = user.Name11__c = user.Name12__c = user.Name13__c = user.Name14__c = user.Name15__c = user.Name16__c = user.Name17__c = user.Name18__c = user.Name19__c = user.Name20__c = user.Name21__c = user.Name22__c = user.Name23__c = user.Name24__c = user.Name25__c = user.Name26__c = user.Name27__c = user.Name28__c = user.Name29__c = user.Name30__c = user.Value1__c = user.Value2__c = user.Value3__c = user.Value4__c = user.Value5__c = user.Value6__c = user.Value7__c = user.Value8__c = user.Value9__c = user.Value10__c = user.Value11__c = user.Value12__c = user.Value13__c = user.Value14__c = user.Value15__c = user.Value16__c = user.Value17__c = user.Value18__c = user.Value19__c = user.Value20__c = user.Value21__c = user.Value22__c = user.Value23__c = user.Value24__c = user.Value25__c = user.Value26__c = user.Value27__c = user.Value28__c = user.Value29__c = user.Value30__c = user.Name31__c = user.Name32__c = user.Name33__c = user.Name34__c = user.Name35__c = user.Name36__c = user.Name37__c = user.Name38__c = user.Name39__c = user.Name40__c = user.Name41__c = user.Name42__c = user.Name43__c = user.Name44__c = user.Name45__c = user.Name46__c = user.Name47__c = user.Name48__c = user.Name49__c = user.Name50__c = user.Name51__c = user.Name52__c = user.Name53__c = user.Name54__c = user.Value31__c = user.Value32__c = user.Value33__c = user.Value34__c = user.Value35__c = user.Value36__c = user.Value37__c = user.Value38__c = user.Value39__c = user.Value40__c = user.Value41__c = user.Value42__c = user.Value43__c = user.Value44__c = user.Value45__c = user.Value46__c = user.Value47__c = user.Value48__c = user.Value49__c = user.Value50__c = user.Value51__c = user.Value52__c = user.Value53__c = user.Value54__c = '';
                             
                                dataSourceList.add(user);
                                if(dataSourceList.size() == 200)
                                {
                                    update dataSourceList;
                                    dataSourceList.clear();
                                }
            
                            }//end of inner for
                        }//end of outer for     
                    }//end of else

                    if(dataSourceList.size() > 0)
                    {
                        update dataSourceList;
                        dataSourceList.clear();
                    }
                    
                }
            }       

        }
        
        return message;
    }
  
    /**
     *  This code block runs in Batch mode.
     */
    Webservice static String populateBatchedUsersForSelectDataSource(String dataSourceListArray, String templateId)
    {
        SObject sObj = new BatchedUser__c();
        DataAccessControlUtil dacu = new DataAccessControlUtil();   
        String message = dacu.isCreateableObjectByUser(sObj);
        
        //Enters only if the User has the permission to create BatchedUser__c object        
        if(message.equalsIgnoreCase('success'))
        {
            //This flag decides whether User can update all the expected fields.
            Boolean canCreateBatchedUserFieldsFlag = false;
            Map<String, SObjectField> batchedUserFieldMap = dacu.getFieldMap(sObj);
            
            //Note: Whenever a new Custom field has to be updated, add it to the below Set.
            //Reason: The size of the below set will be compared with the size of the filtered set 
            Set<String> expectedBUFields = new Set<String>{'TemplateId__c', 'UserId__c', 'UserRoleId__c', 'Batchid__c', 'User_Title__c','User__c','Template__c'};
            
            //get Filtered Creatable fields for the User 
            Set<String> filteredBUFields = dacu.getFilteredCreateableFields(batchedUserFieldMap, expectedBUFields);
            
            //Fails, if atleast one of the expected field(i.e.'TemplateId__c', 'UserId__c', 'UserRoleId__c', 'Batchid__c', 'User_Title__c') cannot be created by the User
            for(String s: expectedBUFields)
            {
                if(!filteredBUFields.contains(s))
                {
                    canCreateBatchedUserFieldsFlag = false;
                    break;
                }
                else 
                    canCreateBatchedUserFieldsFlag = true;
            }
            
            //Enters only if the User has the permission to create all the expected fields, (i.e.'TemplateId__c', 'UserId__c', 'UserRoleId__c', 'Batchid__c', 'User_Title__c')
            if(canCreateBatchedUserFieldsFlag)
            {
                String[] userIdList = new List<String>();
                String[] roleIdList = new List<String>();
                String batchId = '';
        
                if(testFlag == false)
                    batchId = PopulateBatchedUsers.populateObject(userIdList, roleIdList, templateId, 'null');
                
                BatchedUser__c bu;    
                
                String[] dataSourceList = dataSourceListArray.split(',');
                
                SObject cdsObj = new CallidusDataSource__c();
        
                Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(cdsObj);
                
                String[] cdsExpectedFields = new String[]{'FirstName__c','LastName__c','UserID__c','UserRoleId__c','UserRoleName__c','User_Title__c'}; 
                Set<String> allowedFields = dacu.getAccessibleFields(cdsObj, fieldMap, cdsExpectedFields);
                
                String constructSoql = '';
                if(!allowedFields.isEmpty())
                {
                    constructSoql = 'Select ';
                    for(String roField: allowedFields)
                    {
                        constructSoql += roField+', ';
                    }
                    constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
                    constructSoql += ' from CallidusDataSource__c ';
                }                   
                
                String dataSourceId = '';
                List<BatchedUser__c> buList = new List<BatchedUser__c>();
                    
                /**
                 *  Not following sObject.put(f, null) approach, because this block gets executed based upon the canCreateBatchedUserFieldsFlag.
                 */
                for(CallidusDataSource__c[] cds  : Database.query(constructSoql+' where Id in :dataSourceList and IsActive__c = true '))//[select UserID__c, User_Title__c, UserRoleId__c, FirstName__c, LastName__c, UserRoleName__c from CallidusDataSource__c where Id = :dataSourceList[i]];
                {
                    for(CallidusDataSource__c c: cds)
                    {
                        bu = new BatchedUser__c();
                        bu.TemplateId__c = templateId;
                        bu.Template__c = templateId;
                        bu.UserId__c = c.UserID__c;
                        bu.UserRoleId__c = c.UserRoleId__c;
                        bu.User__c = c.UserID__c;
                        bu.Batchid__c = batchId;
                        bu.User_Title__c = c.User_Title__c;
                        buList.add(bu);
                      
                        try
                        {
                            if(buList.size() == 200)
                            {
                                insert buList;
                                buList.clear();
                            }
                
                        }
                        catch(Exception e)
                        {
                            return e.getMessage();
                        }
                    }
                }
                if(buList.size() > 0)
                {
                    insert buList;
                    buList.clear();
                }
                        
                return batchId;
            }
        }
        
        return null;
    }

    //This code block runs in Batch process.
    Webservice static String generateUsers(String str)
    {
        SObject cdsObj = new CallidusDataSource__c();
        DataAccessControlUtil dacu = new DataAccessControlUtil();   
        String message = dacu.isCreateableObjectByUser(cdsObj);
        String message1 = dacu.isUpdateableObjectByUser(cdsObj);
        
        //Satisfies for Users with Update permission on CallidusDataSorce__c object
        if(message.equalsIgnoreCase('success') && message1.equalsIgnoreCase('success'))
        {
            CallidusDataSource__c[] newDataSource = new List<CallidusDataSource__c>();
            CallidusDataSource__c[] existingDataSource = new List<CallidusDataSource__c>();
            CallidusDataSource__c cUser = null;
        
            Map<ID, CallidusDataSource__c> cdsList1 =  new Map<ID, CallidusDataSource__c>();
            Map<ID, CallidusDataSource__c> cdsList2 =  new Map<ID, CallidusDataSource__c>();
            Map<ID, CallidusDataSource__c> cdsList3 =  new Map<ID, CallidusDataSource__c>();
        
            Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(cdsObj);
            
            //Note: Whenever a new Custom field has to be updated, add it to the below Set.
            //Reason: The size of the below set will be compared with the size of the filtered set 
            Set<String> cdsUpdatedFields = new Set<String>{'Name','LastName__c','FirstName__c','UserID__c','UserRoleId__c','UserRoleName__c','User_Title__c'}; 
            Set<String> filteredFields = dacu.getFilteredUpdateableFields(fieldMap, cdsUpdatedFields);


            //Note: Whenever a new Custom field has to be created, add it to the below Set.
            //Reason: The size of the below set will be compared with the size of the filtered set 
            Set<String> cdsCreateableFields = new Set<String>{'Name','LastName__c','FirstName__c','UserID__c','UserRoleId__c','UserRoleName__c','User_Title__c'}; 
            Set<String> filteredCreateableFields = dacu.getFilteredCreateableFields(fieldMap, cdsCreateableFields);

            String constructSoql = '';

            //Enters only if the filteredList size is equivalent to the size of expected createable and updateable fields List 
            if(filteredFields.size() == cdsUpdatedFields.size() && filteredCreateableFields.size() == cdsCreateableFields.size())
            {
                constructSoql = 'Select ';
                for(String roField: filteredFields)
                {
                    constructSoql += roField+', ';
                }
                constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
                constructSoql += ' from CallidusDataSource__c';

                for(List<CallidusDataSource__c> dataSourceList: Database.query(constructSoql))//[SELECT Id, Name, LastName__c, FirstName__c, UserID__c, UserRoleId__c, UserRoleName__c,User_Title__c from CallidusDataSource__c])
                {
                    for(CallidusDataSource__c cds: dataSourceList)
                    {
                        if(cdsList1.size() < 1000)
                            cdsList1.put(cds.UserID__c, cds);
                        else if(cdsList2.size() < 1000)
                            cdsList2.put(cds.UserID__c, cds);
                        else if(cdsList3.size() < 1000)
                            cdsList3.put(cds.UserID__c, cds);
                    }
                }
                
                SObject uObj = new User();
                Map<String, Schema.SObjectField> uFieldMap = dacu.getFieldMap(uObj);
                
                String[] userExpectedFields = new String[]{'Id','LastName','FirstName','IsActive', 'Title'};
             
                Set<String> allowedFields = dacu.getAccessibleFields(uObj, uFieldMap, userExpectedFields);
    
                if(!allowedFields.isEmpty())
                {
                    constructSoql = 'Select ';
                    for(String roField: allowedFields)
                    {
                        constructSoql += roField+', ';
                    }
                    constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
                    String license = 'License';
                    constructSoql += ' , UserRole.Id, UserRole.Name from User u where u.FirstName != :license and u.IsActive = true order by FirstName ';
                    for(User[] userList: Database.query(constructSoql))//[SELECT Id, LastName, FirstName, IsActive, UserRole.Id, UserRole.Name,Title FROM User u where u.FirstName != 'License' and u.IsActive = true order by FirstName])
                    {
                        for(User user: userList)
                        {
                            cUser = null;
                            if(cdsList1.size() > 0)
                                cUser = cdsList1.get(user.Id);
                            if(cUser == null && cdsList2.size() > 0)
                                cUser = cdsList2.get(user.Id);
                            if(cUser == null && cdsList3.size() > 0)
                                cUser = cdsList3.get(user.Id);
                            
                            if(cUser != null)
                            {
                                //Not following the sObject.put() approach to null out non updateable fields, as the below code executes in batch process. There is a possible chance of hitting the limitation of 200000 script statements. 
                                if(user.FirstName != null)
                                {
                                    cUser.Name = user.FirstName+' '+user.LastName;
                                }
                                else if(user.FirstName == null)
                                {
                                    cUser.Name = user.LastName;
                                }
                                
                                cUser.FirstName__c = user.FirstName;
                                cUser.LastName__c = user.LastName;
                                cUser.UserID__c = user.Id;
                                cUser.UserRoleId__c = user.UserRole.Id;
                                cUser.UserRoleName__c = user.UserRole.Name;
                                cUser.User_Title__c = user.Title;
                                existingDataSource.add(cUser);
                                if(existingDataSource.size() == 200)
                                {
                                    update existingDataSource;
                                    existingDataSource.clear();
                                }
                                
                            }
                            else
                            {
                                cUser = new CallidusDataSource__c();
                    
                                if(user.FirstName != null)
                                {
                                    cUser.Name = user.FirstName+' '+user.LastName;
                                }
                                else if(user.FirstName == null)
                                {
                                    cUser.Name = user.LastName;
                                }
                    
                                cUser.FirstName__c = user.FirstName;
                                cUser.LastName__c = user.LastName;
                                cUser.UserID__c = user.Id;
                                cUser.UserRoleId__c = user.UserRole.Id;
                                cUser.UserRoleName__c = user.UserRole.Name;
                                cUser.User_Title__c = user.Title;
                                newDataSource.add(cUser);
                                if(newDataSource.size() == 200)
                                {
                                    insert newDataSource;
                                    newDataSource.clear();
                                }
                                
                            }
                        }
                    }

                }               
                
            }               
        
            if(newDataSource.size() > 0)
            {
                insert newDataSource;
                newDataSource.clear();
            }
            if(existingDataSource.size() > 0)
            {
                update existingDataSource;
                existingDataSource.clear();
            }
        }
        return message;
    }
    
    
    /**
     *  This code block runs in Batch mode.
     */
    Webservice static String insertBUForDS(String dataSourceListArray)
    {
        SObject sObj = new BatchedUser__c();
        DataAccessControlUtil dacu = new DataAccessControlUtil();   
        String message = dacu.isCreateableObjectByUser(sObj);
        
        //Enters only if the User has the permission to create BatchedUser__c object        
        if(message.equalsIgnoreCase('success'))
        {
            //This flag decides whether User can update all the expected fields.
            Boolean canCreateBatchedUserFieldsFlag = false;
            Map<String, SObjectField> batchedUserFieldMap = dacu.getFieldMap(sObj);
            
            //Note: Whenever a new Custom field has to be updated, add it to the below Set.
            //Reason: The size of the below set will be compared with the size of the filtered set 
            Set<String> expectedBUFields = new Set<String>{'TemplateId__c', 'UserId__c', 'UserRoleId__c', 'Batchid__c', 'User_Title__c','User__c','Template__c'};
            
            //get Filtered Creatable fields for the User 
            Set<String> filteredBUFields = dacu.getFilteredCreateableFields(batchedUserFieldMap, expectedBUFields);
            
            //Fails, if atleast one of the expected field(i.e.'TemplateId__c', 'UserId__c', 'UserRoleId__c', 'Batchid__c', 'User_Title__c') cannot be created by the User
            for(String s: expectedBUFields)
            {
                if(!filteredBUFields.contains(s))
                {
                    canCreateBatchedUserFieldsFlag = false;
                    break;
                }
                else 
                    canCreateBatchedUserFieldsFlag = true;
            }
            
            //Enters only if the User has the permission to create all the expected fields, (i.e.'TemplateId__c', 'UserId__c', 'UserRoleId__c', 'Batchid__c', 'User_Title__c')
            if(canCreateBatchedUserFieldsFlag)
            {
                String[] userIdList = new List<String>();
                String[] roleIdList = new List<String>();
                Batch__c batch = new Batch__c();
				insert batch;
				                
                BatchedUser__c bu;    
                
                String[] dataSourceList = dataSourceListArray.split(',');
                
                SObject cdsObj = new CallidusDataSource__c();
        
                Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(cdsObj);
                
                String[] cdsExpectedFields = new String[]{'FirstName__c','LastName__c','UserID__c','UserRoleId__c','UserRoleName__c','Template__c','User_Title__c'}; 
                Set<String> allowedFields = dacu.getAccessibleFields(cdsObj, fieldMap, cdsExpectedFields);
                
                String constructSoql = '';
                if(!allowedFields.isEmpty())
                {
                    constructSoql = 'Select ';
                    for(String roField: allowedFields)
                    {
                        constructSoql += roField+', ';
                    }
                    constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
                    constructSoql += ' from CallidusDataSource__c ';
                }                   
                
                String dataSourceId = '';
                List<BatchedUser__c> buList = new List<BatchedUser__c>();
                    
                /**
                 *  Not following sObject.put(f, null) approach, because this block gets executed based upon the canCreateBatchedUserFieldsFlag.
                 */
                for(CallidusDataSource__c[] cds  : Database.query(constructSoql+' where Id in :dataSourceList and IsActive__c = true '))//[select UserID__c, User_Title__c, UserRoleId__c, FirstName__c, LastName__c, UserRoleName__c from CallidusDataSource__c where Id = :dataSourceList[i]];
                {
                    for(CallidusDataSource__c c: cds)
                    {
                        bu = new BatchedUser__c();
                        bu.TemplateId__c = c.Template__c;
                        bu.Template__c = c.Template__c;
                        bu.UserId__c = c.UserID__c;
                        bu.User__c = c.UserID__c;
                        bu.UserRoleId__c = c.UserRoleId__c;
                        bu.Batchid__c = batch.id;
                        bu.User_Title__c = c.User_Title__c;
                        buList.add(bu);
                      
                        try
                        {
                            if(buList.size() == 200)
                            {
                                insert buList;
                                buList.clear();
                            }
                
                        }
                        catch(Exception e)
                        {
                            return e.getMessage();
                        }
                    }
                }
                if(buList.size() > 0)
                {
                    insert buList;
                    buList.clear();
                }
                        
                return batch.Id;
            }
        }
        
        return null;
    }
    
    //This code block runs in Batch process.
    Webservice static String generateUsers2()
    {
        Callidus_DataSourceBatchUtil cds = new Callidus_DataSourceBatchUtil();
        
        ID batchApexId = Database.executeBatch(cds);
        return 'success';
    }    

    Webservice static CallidusDataSource__c[] getDataSourceList()
    {
        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject cdsObj = new CallidusDataSource__c();

        Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(cdsObj);
        
        String[] cdsExpectedFields = new String[]{'Id','Name','FirstName__c','LastName__c','UserID__c','UserRoleId__c','UserRoleName__c','Name1__c','Name2__c','Name3__c','Name4__c','Name5__c','Name6__c','Name7__c','Name8__c','Name9__c','Name10__c','Name11__c','Name12__c','Name13__c','Name14__c','Name15__c','Name16__c','Name17__c','Name18__c','Name19__c','Name20__c','Name21__c','Name22__c','Name23__c','Name24__c','Name25__c','Name26__c','Name27__c','Name28__c','Name29__c','Name30__c','Value1__c','Value2__c','Value3__c','Value4__c','Value5__c','Value6__c','Value7__c','Value8__c','Value9__c','Value10__c','Value11__c','Value12__c','Value13__c','Value14__c','Value15__c','Value16__c','Value17__c','Value18__c','Value19__c','Value20__c','Value21__c','Value22__c','Value23__c','Value24__c','Value25__c','Value26__c','Value27__c','Value28__c','Value29__c','Value30__c','Name31__c','Name32__c','Name33__c','Name34__c','Name35__c','Name36__c','Name37__c','Name38__c','Name39__c','Name40__c','Name41__c','Name42__c','Name43__c','Name44__c','Name45__c','Name46__c','Name47__c','Name48__c','Name49__c','Name50__c','Name51__c','Name52__c','Name53__c','Name54__c','Value31__c','Value32__c','Value33__c','Value34__c','Value35__c','Value36__c','Value37__c','Value38__c','Value39__c','Value40__c','Value41__c','Value42__c','Value43__c','Value44__c','Value45__c','Value46__c','Value47__c','Value48__c','Value49__c','Value50__c','Value51__c','Value52__c','Value53__c','Value54__c'}; 
        Set<String> allowedFields = dacu.getAccessibleFields(cdsObj, fieldMap, cdsExpectedFields);
        CallidusDataSource__c[] dsList = null;
        
        String constructSoql = '';
        if(!allowedFields.isEmpty())
        {
            constructSoql = 'Select ';
            for(String roField: allowedFields)
            {
                constructSoql += roField+', ';
            }
            constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
            constructSoql += ' from CallidusDataSource__c';
            
            if(constructSoql.contains('Id'))
            {
                dsList = Database.query(constructSoql);//[SELECT Id, Name, FirstName__c, LastName__c, UserID__c, UserRoleId__c, UserRoleName__c, Name1__c, Name2__c, Name3__c, Name4__c, Name5__c, Name6__c, Name7__c, Name8__c, Name9__c, Name10__c, Name11__c, Name12__c, Name13__c, Name14__c, Name15__c, Name16__c, Name17__c, Name18__c, Name19__c, Name20__c, Name21__c, Name22__c, Name23__c, Name24__c, Name25__c, Name26__c, Name27__c, Name28__c, Name29__c, Name30__c, Value1__c, Value2__c, Value3__c, Value4__c, Value5__c, Value6__c, Value7__c, Value8__c, Value9__c, Value10__c, Value11__c, Value12__c, Value13__c, Value14__c, Value15__c, Value16__c, Value17__c, Value18__c, Value19__c, Value20__c, Value21__c, Value22__c, Value23__c, Value24__c, Value25__c, Value26__c, Value27__c, Value28__c, Value29__c, Value30__c, Name31__c, Name32__c, Name33__c, Name34__c, Name35__c, Name36__c, Name37__c, Name38__c, Name39__c, Name40__c, Name41__c, Name42__c, Name43__c, Name44__c, Name45__c, Name46__c, Name47__c, Name48__c, Name49__c, Name50__c, Name51__c, Name52__c, Name53__c, Name54__c, Value31__c, Value32__c, Value33__c, Value34__c, Value35__c, Value36__c, Value37__c, Value38__c, Value39__c, Value40__c, Value41__c, Value42__c, Value43__c, Value44__c, Value45__c, Value46__c, Value47__c, Value48__c, Value49__c, Value50__c, Value51__c, Value52__c, Value53__c, Value54__c FROM CallidusDataSource__c];
            }
        }
        return dsList;
    }
    
    //@ method to get plan details
    Webservice static CallidusDataSource__c getPlanInfo(Id dsId)
    {
        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject cdsObj = new CallidusDataSource__c();

        Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(cdsObj);
        
        String[] cdsExpectedFields = new String[]{'Id','Name','FirstName__c','LastName__c','UserID__c','UserRoleId__c','UserRoleName__c','Name1__c','Name2__c','Name3__c','Name4__c','Name5__c','Name6__c','Name7__c','Name8__c','Name9__c','Name10__c','Name11__c','Name12__c','Name13__c','Name14__c','Name15__c','Name16__c','Name17__c','Name18__c','Name19__c','Name20__c','Name21__c','Name22__c','Name23__c','Name24__c','Name25__c','Name26__c','Name27__c','Name28__c','Name29__c','Name30__c','Value1__c','Value2__c','Value3__c','Value4__c','Value5__c','Value6__c','Value7__c','Value8__c','Value9__c','Value10__c','Value11__c','Value12__c','Value13__c','Value14__c','Value15__c','Value16__c','Value17__c','Value18__c','Value19__c','Value20__c','Value21__c','Value22__c','Value23__c','Value24__c','Value25__c','Value26__c','Value27__c','Value28__c','Value29__c','Value30__c','Name31__c','Name32__c','Name33__c','Name34__c','Name35__c','Name36__c','Name37__c','Name38__c','Name39__c','Name40__c','Name41__c','Name42__c','Name43__c','Name44__c','Name45__c','Name46__c','Name47__c','Name48__c','Name49__c','Name50__c','Name51__c','Name52__c','Name53__c','Name54__c','Value31__c','Value32__c','Value33__c','Value34__c','Value35__c','Value36__c','Value37__c','Value38__c','Value39__c','Value40__c','Value41__c','Value42__c','Value43__c','Value44__c','Value45__c','Value46__c','Value47__c','Value48__c','Value49__c','Value50__c','Value51__c','Value52__c','Value53__c','Value54__c'}; 
        Set<String> allowedFields = dacu.getAccessibleFields(cdsObj, fieldMap, cdsExpectedFields);
        
        String constructSoql = '';
        CallidusDataSource__c ds = null;
        if(!allowedFields.isEmpty())
        {
            constructSoql = 'Select ';
            for(String roField: allowedFields)
            {
                constructSoql += roField+', ';
            }
            constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
            constructSoql += ' from CallidusDataSource__c where id = :dsId';
            
            if(constructSoql.contains('Id'))
            {
                ds = Database.query(constructSoql);
            }
        }
        return ds;
    }
    
 
    Webservice static String[] getTemplateDetails()
    {
        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject tObj = new Template__c();

        Map<String, Schema.SObjectField> fieldMap = dacu.getFieldMap(tObj);
        
        String[] tExpectedFields = new String[]{'Id','Name'}; 
        Set<String> allowedFields = dacu.getAccessibleFields(tObj, fieldMap, tExpectedFields);
        String[] tempRec = new String[2];
        
        String constructSoql = '';
        if(!allowedFields.isEmpty())
        {
            constructSoql = 'Select ';
            for(String roField: allowedFields)
            {
                constructSoql += roField+', ';
            }
            constructSoql = constructSoql.substring(0, constructSoql.length() - 2);
            constructSoql += ' from Template__c';

            tExpectedFields = new String[]{'Status__c'}; 
            allowedFields = dacu.getAccessibleFields(tObj, fieldMap, tExpectedFields);
            
            if(!allowedFields.isEmpty())
            {
                constructSoql += ' where ';
                String inUse = 'In Use'; 
                for(String roField: allowedFields)
                {
                    constructSoql += roField+' = :inUse  order by CreatedDate desc limit 1';
                }
                
                if(constructSoql.contains('Id'))
                {
                    Template__c[] t = Database.query(constructSoql);//[select Id, Name from Template__c where Status__c = 'In Use' order by CreatedDate desc limit 1];
                    if(t.size() > 0)
                    {
                        tempRec[0] = t[0].Id;
                        tempRec[1] = t[0].Name;
                    }
                }
            }           
            
        }
        return tempRec;
    }
    
    static testMethod void testCase() 
    {
        CallidusDataSource__c cds = new CallidusDataSource__c(UserID__c = Userinfo.getUserId());
        
        Template__c t = new Template__c(name= 'DataSource', status__c = 'In Use');
        Template__c t1 = new Template__c(name= 'DataSource', status__c = 'In Use');
        
        Test.startTest();
        insert t;
        Template__c[] testT = [select name from Template__c where  id = :t.id];
        system.assertEquals('DataSource', testT[0].name);
        
        insert cds;
        CallidusDataSource__c[] cdsT = [select UserID__c from CallidusDataSource__c where UserID__c = :UserInfo.getUserID()];
        system.assertEquals(UserInfo.getUserId(), cdsT[0].UserID__c);
        
        system.assertEquals(cds.UserID__c, getPlanParticipantDetails(cds.Id).UserID__c);
        
        Attachment a = new Attachment(name = 'Test Attach.doc', Body = Blob.valueOf('<html><body>This is {Attachment}</body></html>'), parentId = cds.Id);
        insert a;
        Attachment[] aT = [select Id, Name from Attachment a where a.ParentId = :cds.id];
        if(aT.size() > 0)
        {
            aT[0].Name = 'Test 2.txt';
            update aT;
        }
        getDataSourceList();
        String[] stArr = new String[2];
        stArr[0] = t.id;
        stArr[1] = t.Name; 
        
        system.assertEquals('success', purgeUsers('test'));
//        system.assertEquals('success', generateUsers('fromTestMethod'));
        System.assertEquals('success', deleteUsers('test'));
        System.assertEquals(getTemplateDetails(), stArr);
        
        testFlag = true;
        populateBatchedUsersForSelectDataSource(cds.id, t.id);
        System.assertEquals('success', generateUsers(''));
        Test.stopTest();

    }

    static testMethod void testCase2() 
    {
        CallidusDataSource__c cds = new CallidusDataSource__c(UserID__c = Userinfo.getUserId());
        
        Template__c t = new Template__c(name= 'DataSource', status__c = 'In Use');
        Template__c t1 = new Template__c(name= 'DataSource', status__c = 'In Use');
        
        Test.startTest();
        insert t;
        Template__c[] testT = [select name from Template__c where  id = :t.id];
        system.assertEquals('DataSource', testT[0].name);
        
        insert cds;
        CallidusDataSource__c[] cdsT = [select UserID__c from CallidusDataSource__c where UserID__c = :UserInfo.getUserID()];
        system.assertEquals(UserInfo.getUserId(), cdsT[0].UserID__c);
        
        system.assertEquals(cds.UserID__c, getPlanParticipantDetails(cds.Id).UserID__c);
        
        Attachment a = new Attachment(name = 'Test Attach.doc', Body = Blob.valueOf('<html><body>This is {Attachment}</body></html>'), parentId = cds.Id);
        insert a;
        Attachment[] aT = [select Id, Name from Attachment a where a.ParentId = :cds.id];
        if(aT.size() > 0)
        {
            aT[0].Name = 'Test 2.txt';
            update aT;
        }
        getDataSourceList();
        String[] stArr = new String[2];
        stArr[0] = t.id;
        stArr[1] = t.Name; 
        
        system.assertEquals('success', purgeUsers('test'));
//        system.assertEquals('success', generateUsers('fromTestMethod'));
        System.assertEquals('success', deleteUsers('test'));
        System.assertEquals(getTemplateDetails(), stArr);
        
        testFlag = true;
        populateBatchedUsersForSelectDataSource(cds.id, t.id);
        generateUsers2();
        Test.stopTest();

    }
    
    static testMethod void testCase3() 
    {
        CallidusDataSource__c cds = new CallidusDataSource__c(UserID__c = Userinfo.getUserId());
        
        Template__c t = new Template__c(name= 'DataSource', status__c = 'In Use');
        Template__c t1 = new Template__c(name= 'DataSource', status__c = 'In Use');
        
        Test.startTest();
        insert t;
        Template__c[] testT = [select name from Template__c where  id = :t.id];
        system.assertEquals('DataSource', testT[0].name);
        
        insert cds;
        CallidusDataSource__c[] cdsT = [select UserID__c from CallidusDataSource__c where UserID__c = :UserInfo.getUserID()];
        system.assertEquals(UserInfo.getUserId(), cdsT[0].UserID__c);
        
        system.assertEquals(cds.UserID__c, getPlanParticipantDetails(cds.Id).UserID__c);
        
        Attachment a = new Attachment(name = 'Test Attach.doc', Body = Blob.valueOf('<html><body>This is {Attachment}</body></html>'), parentId = cds.Id);
        insert a;
        Attachment[] aT = [select Id, Name from Attachment a where a.ParentId = :cds.id];
        if(aT.size() > 0)
        {
            aT[0].Name = 'Test 2.txt';
            update aT;
        }
        
        getPlanInfo(cds.Id);
        Test.stopTest();

    }

    static testMethod void dacuTestCase() 
    {
        DataAccessControlUtil dacu = new DataAccessControlUtil();
        SObject sObj = new CallidusDataSOurce__c();
        Map<String, Schema.Sobjectfield> fieldsMap = dacu.getFieldMap(sObj);
        String[] expectedFieldMap = new String[]{'Id','Name'};
        Set<String> allowedFields = dacu.getAccessibleFields(sObj, fieldsMap, expectedFieldMap);
        Set<String> filteredList = dacu.getFilteredCreateableFields(fieldsMap, allowedFields);
        filteredList = dacu.getFilteredUpdateableFields(fieldsMap, allowedFields);
        system.assertEquals('success', dacu.isCreateableObjectByUser(sObj));
        system.assertEquals('success', dacu.isUpdateableObjectByUser(sObj));
        system.assertEquals('success', dacu.isDeleteableObjectByUser(sObj));
        dacu.pageMessage(sobj, 'create');
    }
 }